#include "ZWalker.h"
#include "ZAWays.h"
#include "ZMap.h"
using namespace std;
namespace Zdib
{
	CWalker::CWalker(CContainer *root,CContainer *parent,char *filename):CImager(root,parent,filename)
	{
		m_Load=new TZList(100);
		ChangeSpeed(14);
		m_NowPos=0;
		m_MoveTime=NULL;
		m_TarGrid=NULL;
		m_MoveDir=0;
	}

	CWalker::~CWalker()
	{
		FreeCallBack(m_MoveTime);
		m_MoveTime=NULL;
		delete m_Load;
	}
	
	void CWalker::WalkTo(TPos pos,int speed)
	{
		TPos nowpos;
		CMap *map;
		PGrid nowpg,tarpg;
		FreeCallBack(m_MoveTime);
		m_MoveTime=NULL;
		nowpos=GetPos();
		map=(Zdib::CMap *)m_Parent;
		nowpg=map->GetObstruct()->GetGridForPos(nowpos);
		tarpg=map->GetObstruct()->GetGridForPos(pos);
		if(!GridPass(tarpg->data))
		{
			tarpg=map->GetObstruct()->GetNear(tarpg,nowpg);
		}
		m_Load->delall();
		m_NowPos=0;
		ChangeSpeed(speed);
		map->GetObstruct()->GetLoad(m_Load,nowpg,tarpg);
		if(m_Load->count==0)
			return;
		m_TarGrid=NULL;
		m_MoveTime=SetCallBack((LPVOID)this,WalkMove,1);
	}
	
	void CWalker::ChangeSpeed(int speed)
	{
		if(speed<=0)
			speed=1;
		m_Speed=speed;
	}

	void CWalker::CalMove(PGrid targ)
	{
		int disy,disx;
		float dis,rate;
		TPos movetopos,nowpos;
		movetopos=CalXY(targ->data);
		nowpos=GetPos();
		disx=-nowpos.x+movetopos.x;
		disy=-nowpos.y+movetopos.y;
		dis=sqrt(float(disx*disx+disy*disy));
		rate=float(m_Speed)/dis;
		m_MoveCount=int(1.0/rate);

		m_MoveX=int(disx*rate);
		m_MoveY=int(disy*rate);
	}

	CHero::CHero(CContainer *root,CContainer *parent,char *filename):CWalker(root,parent,filename)
	{
		m_MoveMapTime=NULL;
	}

	CHero::~CHero()
	{
		FreeCallBack(m_MoveMapTime);
	}

	void CHero::WalkTo(TPos pos,int speed)
	{
		CWalker::WalkTo(pos,speed);
		FreeCallBack(m_MoveMapTime);
		m_MoveMapTime=NULL;
		m_MoveMapTime=SetCallBack((LPVOID)this,MapMove,2);
	}
}

LPVOID WalkMove(LPVOID lp,LPVOID argv[])
{
	Zdib::CWalker *walkobj;
	PGrid tempg,nextpg;
	TZList *temproad;
	int i,j;
	BYTE olddir;
	TPos nowpos;
	walkobj=(Zdib::CWalker *)lp;
	temproad=walkobj->GetPath();
	if(walkobj->GetNowPosForPath()>=temproad->count-1 && walkobj->m_TarGrid==NULL)
	{
		walkobj->m_MoveTime=NULL;
		return NULL;
	}
	if(walkobj->m_TarGrid==NULL)
	{
		olddir=8;
		for(i=walkobj->GetNowPosForPath();i<temproad->count-1;i++)
		{
			tempg=(PGrid)temproad->items(i);
			nextpg=(PGrid)temproad->items(i+1);
			for(j=0;j<8;j++)
			{
				if(nextpg==tempg->DirPoint[j])
				{
					if(olddir==8)
					{
						olddir=j;
						walkobj->m_MoveDir=j;
						break;
					}
					if(olddir!=j)
					{
						walkobj->m_TarGrid=tempg;
						break;
					}
					else
					{
						break;
					}
				}
			}
			if(walkobj->m_TarGrid!=NULL)
			{
				walkobj->CalMove(walkobj->m_TarGrid);
				break;
			}
			walkobj->AddNowPosForPath();
		}
	}
	if(walkobj->m_TarGrid==NULL)
	{
		walkobj->m_TarGrid=(PGrid)temproad->items(walkobj->GetNowPosForPath());
		walkobj->CalMove(walkobj->m_TarGrid);
	}
	
	walkobj->SetCurDir(walkobj->m_MoveDir);
	nowpos=walkobj->GetPos();
	nowpos.x+=walkobj->m_MoveX;
	nowpos.y+=walkobj->m_MoveY;
	walkobj->SetPos(nowpos.x,nowpos.y);
	walkobj->m_MoveCount-=1;
	if(walkobj->m_MoveCount<=0)
	{
		walkobj->m_TarGrid=NULL;
	}
	return lp;
}

LPVOID MapMove(LPVOID lp,LPVOID argv[])
{
	Zdib::CHero *hero;
	Zdib::CMap *map;
	TZList *temproad;
	TPos NowPos;
	hero=(Zdib::CHero *)lp;
	
	temproad=hero->GetPath();
	if(hero->GetNowPosForPath()>=temproad->count-1)
	{
		hero->m_MoveMapTime=NULL;
		return NULL;
	}
	map=(Zdib::CMap *)hero->GetParent();
	NowPos=hero->GetPos();
	map->SetMapPos(-NowPos.x+ScreenW/2,-NowPos.y+ScreenH/2);
	return lp;
}